package se.pruzelius.aznavainternet;

import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class HttpService extends Service {

    private String[] ALLOWED_URLS = {
            "http://www.avanza.se",
            "https://www.avanza.se/aza/home/home.jsp",
            "https://www.avanza.se/aza/login/login.jsp",
            "https://www.avanza.se/aza/aktieroptioner/kurslistor/dynam_gif_graphd.jsp?orderbookId=18988&type=g&size=s&ur=1&idx=1",
            "https://www.avanza.se/aza/depa/sammanfattning/sammanfattning.jsp",
            "https://www.avanza.se/aza/depa/depa.jsp",

            "https://www.avanza.se/mini/hem/index.html",
            "https://www.avanza.se/mini/logga_in/logga_ut.html",
            "https://www.avanza.se/mini/hem/index.html",
            "https://www.avanza.se/mini/mitt_konto/index.html"
            };


    static HttpClient httpClient = getClient();
    static {
        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
    }

    public class HttpServiceImpl extends se.pruzelius.aznavainternet.IHttpService.Stub {

        public String get(String i_url) throws RemoteException {
            if (urlOK(i_url)) {
                return httpGet(i_url);
            }
            return null;
        }


        public Bitmap getBitmap(String i_url) throws RemoteException {
            if (urlOK(i_url)) {
                try {
                    HttpGet l_httpGet = new HttpGet(i_url);
                    InputStream l_is = getRequestStream(l_httpGet);
                    return BitmapFactory.decodeStream(l_is);
                } catch (Exception e) {
                    Log.e("AznavaInternet", "getBitmap", e);
                    throw new RemoteException();
                }
            }
            return null;
        }

        public String postLogin(String i_username, String i_password) throws RemoteException {
            List<NameValuePair> l_parameters = new ArrayList<NameValuePair>();
            l_parameters.add(new BasicNameValuePair("username", i_username));
            l_parameters.add(new BasicNameValuePair("password", i_password));
            l_parameters.add(new BasicNameValuePair("redirect", ""));
            l_parameters.add(new BasicNameValuePair("service", "M"));
            l_parameters.add(new BasicNameValuePair("msgId", "-1"));
            return httpPost("https://www.avanza.se/aza/login/login.jsp", l_parameters);
        }

        public String postLoginMini(String i_username, String i_password, String i_id) throws RemoteException {
            List<NameValuePair> l_parameters = new ArrayList<NameValuePair>();
            l_parameters.add(new BasicNameValuePair("username", i_username));
            l_parameters.add(new BasicNameValuePair("password", i_password));
            l_parameters.add(new BasicNameValuePair("javax.faces.ViewState", i_id));
            l_parameters.add(new BasicNameValuePair("login", "login"));
            l_parameters.add(new BasicNameValuePair("seamj_id66", "Logga in"));
            l_parameters.add(new BasicNameValuePair("conversationPropagation", "none"));
            return httpPost("https://www.avanza.se/mini/logga_in/", l_parameters);
        }
    }


    private boolean urlOK(String i_url) throws RemoteException {
        boolean l_urlOK = false;
        for (String l_url : ALLOWED_URLS) {
            if (l_url.equals(i_url)) {
                l_urlOK = true;
                break;
            }
        }
        if (!l_urlOK) {
            Log.e("AznavaInternet", "Forbidden url " + i_url);
            throw new RemoteException();
        }
        return l_urlOK;
    }
    
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("AznavaInternet", "service:onCreate");
    }

    @Override
    public IBinder onBind(Intent i_intent) {
        Log.i("AznavaInternet", "service:onBind " + i_intent);
        return new HttpServiceImpl();
    }

    private String httpGet(String i_url) throws RemoteException {
        try {
            HttpGet l_httpGet = new HttpGet(i_url);
            return executeRequest(l_httpGet);
        }
        catch (Exception e) {
            Log.e("AznavaInternet", "httpGet", e);
            throw new RemoteException();
        }
    }

    private String httpPost(String i_url, List<NameValuePair> i_parameters) throws RemoteException {
        try {
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(i_parameters, "UTF-8");
            HttpPost l_httpPost = new HttpPost(i_url);
            l_httpPost.setEntity(entity);
            return executeRequest(l_httpPost);
        }
        catch (Exception e) {
            Log.e("AznavaInternet", "httpPost", e);
            throw new RemoteException();
        }
    }

     private synchronized String executeRequest(HttpUriRequest i_httpUriRequest) throws IOException, InterruptedException {
        String l_ret = "";
        try {
            InputStream l_inputStream = getRequestStream(i_httpUriRequest);
            if (l_inputStream != null) {
                int l;
                byte[] tmp = new byte[2048];
                while ((l = l_inputStream.read(tmp)) != -1) {
                    String l_r = new String(tmp);
                    l_ret += l_r.substring(0, l);
                }
            }
        }
        catch (Exception e) {
            Log.e("AznavaInternet", "executeRequest", e);
        }
        return l_ret;
    }

    private synchronized InputStream getRequestStream(HttpUriRequest i_httpUriRequest) throws IOException, InterruptedException {
        try {
            i_httpUriRequest.setHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 7.0; Windows 2000)");

            HttpResponse response = httpClient.execute(i_httpUriRequest);
            HttpEntity l_httpEntity = response.getEntity();
            return l_httpEntity.getContent();
        }
        catch (Exception e) {
            Log.e("AznavaInternet", "getRequestStream", e);
        }
        return null;
    }

    // -----------------------------------------------------------------------------------------------------------------
    // --------------------------------------------- SSL-problem work-around -------------------------------------------
    // -----------------------------------------------------------------------------------------------------------------

    private static DefaultHttpClient getClient() {
        DefaultHttpClient ret = null;

        // sets up parameters
        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "utf-8");
        params.setBooleanParameter("http.protocol.expect-continue", false);

        // registers schemes for both http and https
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
        ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry);
        ret = new DefaultHttpClient(manager, params);
        return ret;
    }


}
